/*
 * $Id: XLIReader.h,v 1.6 2006-02-10 05:10:12 bacon Exp $
 */

#ifndef _XPP_XLI_XLIREADER_CLASS_
#define _XPP_XLI_XLIREADER_CLASS_

#include <xpp/xli/XLI.h>

namespace xpp
{
	namespace xli
	{

		class XLIReader: public Uncopyable 
		{
		public:
			XLIReader ();
			virtual ~XLIReader ();

			XLI* read ();

			// return -1 on error, 0 on end of input, 1 on success
			virtual int readChar (xp_char_t* c) = 0;
		
			enum ErrCode  
			{
				ERR_NONE = 0,
				ERR_READCHAR,
				ERR_ASSIGNOP,
				ERR_SYMBOL,
				ERR_SYMBOLTOOLONG,
				ERR_SEMICOLON,
				ERR_RBRACE,
				ERR_VALUE,
				ERR_WRONGCHAR,
				ERR_SYSTEM,
				ERR_EXCEPTION
			};
		
			xp_size_t errorLine () const 
			{
				return _line;
			}

			xp_size_t errorCol () const 
			{
				return _col;
			}

			ErrCode errorCode () const 
			{
				return this->error_code;
			}
		
			const xp_char_t* errorStr () const;

		protected:
			class Token
			{
			public:
				friend class XLIReader;
		
				enum Type 
				{
					T_END,
					T_ERROR,
					T_SYMBOL,
					T_STRING,
					T_LBRACE,
					T_RBRACE,
					T_SEMICOLON,
					T_ASSIGN
				};
		
				Token () 
				{ 
					type = T_END;
					name = XP_TEXT("");
				}

				void set (Type t, const xp_char_t* n = XP_TEXT("")) 
				{
					type = t;
					name = n;
				}

				void clear () 
				{
					type = T_END;
					name = XP_TEXT("");
				}
		
			protected:
				Type   type;
				bas::String name;
			};
		
			Token         token;
			xp_size_t     _line;
			xp_size_t     _col;
			xp_size_t     token_line;
			xp_size_t     token_col;
			ErrCode       error_code;

			xp_cint_t     cur_char;
			xp_size_t     cur_line;
			xp_size_t     cur_col;
		
			void clear ();

			XLI*     read_list (bool inList);
			XLICell* read_cell ();
			XLIKey*  read_key  ();
			XLIVal*  read_val  ();
		
			int read_token  ();
			int read_symbol ();
			int read_string (xp_char_t start, bool continued = false);
			int skip_spaces ();
			int skip_comment ();
			int read_char ();
		};

	}
		
}
		
#endif
